S08-09 Node-项目:mr-node-koa2-ejs-weibo
[TOC]
前置知识
EJS
概述
EJS(Embedded JavaScript templates):是一个简单高效的 JS 模板引擎。有如下作用:
- 在 HTML 中嵌入 JS 代码。
- 使用 JS 动态地生成最终的 HTML 页面。
它的主要作用是让开发者能够更容易地将数据(来自数据库、API等)和网页结构(HTML)分离开来,从而创建出动态的网页。
核心特点:
语法简单:
EJS 的语法非常接近于纯 HTML。它使用特定的标签(如
<% %>
)来嵌入 JS 逻辑,学习成本很低。与 JS 无缝集成:
因为你直接在模板里写 JS,所以你可以使用 JS 的所有能力(变量、循环、条件判断、函数等)。
服务端渲染:
EJS 最常用于 Node.js 后端。服务器从数据库获取数据,然后通过 EJS 引擎将数据和模板结合,生成完整的 HTML 字符串,最后将这个字符串发送给客户端浏览器。这对 SEO(搜索引擎优化)非常友好。
语法标签
EJS 使用几种不同的标签来区分不同类型的 JS 代码:
执行控制流
:<% %>
- 执行控制流
用于嵌入JS 逻辑,如 if
条件判断、for
循环等。这里的代码会被执行,但不会向输出结果中添加任何内容。
<% if (user) { %>
<h1>Welcome, <%= user.name %></h1>
<% } else { %>
<h1>Please log in</h1>
<% } %>
输出转移值
:<%= %>
- 输出转义的值
用于输出一个 JS 表达式的值到 HTML 中。
关键点:它会对 HTML 特殊字符(如 <
, >
, &
, "
等)进行转义,以防止 XSS(跨站脚本)攻击。这是最常用的输出标签。
<p>Your username is: <%= username %></p>
<p>Your username is: <%= 1 + 1 %></p>
输出原始 HTML
:<%- %>
- 输出原始 HTML
用于输出未经转义的值。如果你的数据中包含 HTML 标签,并且你希望这些标签在浏览器中被渲染出来,而不是被显示为文本,就用这个标签。
注意:使用此标签时要确保数据来源是可信的,否则有 XSS 风险。
<!-- 假设 article.content 是 '<p>This is a paragraph.</p>' -->
<div><%- article.content %></div>
<!-- 最终渲染结果将是一个真正的段落 -->
注释
:<%# %>
- 注释
模板内部的注释,不会出现在最终输出中。
<%# This is a comment, it will be ignored %>
包含其他模板
:<%- include(...) %>
- 包含其他模板
允许你将另一个 EJS 文件(如页头、页脚、导航栏)包含到当前模板中,实现代码复用。
<!DOCTYPE html>
<html>
<head>
<%- include('partials/head') %>
</head>
<body>
<%- include('partials/header') %>
<main>
<!-- 主要内容 -->
</main>
<%- include('partials/footer') %>
</body>
</html>
案例:Node 渲染
app.set():
(name, value)
,Express 中用于设置应用程序配置的函数。常见用途:
设置应用程序标题:
jsapp.set('title', '某个标题')
设置模板引擎:
jsapp.set('view engine', 'ejs')
指定视图文件所在目录:
jsapp.set('views', './views')
设置运行环境(生产/开发):
jsapp.set('env', 'production')
启用或禁用功能:
布尔值配置项可以通过
app.set
启用或禁用。jsapp.set('case sensitive routing', true); // 区分大小写路由
res.render():
(template, data?, options?)
,将一个 EJS 模板字符串和一个数据对象组合起来,编译并渲染成最终的 HTML 字符串。options 选项:用于控制 EJS 引擎的多种行为。
选项名 类型 默认值 描述 cache
Boolean false
如果为 true
,当使用ejs.renderFile()
时会缓存编译后的函数。对于重复渲染相同的模板文件非常高效。(主要对renderFile
有用)filename
String null
模板的文件名。它有两个关键作用: 1. 用于缓存(当 cache: true
时)。 2. 用于解析include()
中的相对路径。如果你想使用include
,这个选项几乎是必需的。root
String null
与 views
同义,设置项目的根目录,用于解析include
的相对路径。Express 会默认设置这个。views
Array []
一个目录路径数组,当使用 include
时,EJS 会从这些路径中查找模板。context
Any null
替换 data
对象,作为模板执行的根上下文。不常用。compileDebug
Boolean true
(开发)false
(生产)如果为 true
,会在编译生成的函数中包含行号信息,用于产生更准确的错误堆栈。生产环境应设为false
以提升性能。client
Boolean false
返回一个独立的、可编译模板的函数,以便在浏览器端使用。 delimiter
String %
用于修改 EJS 标签的分隔符。例如 delimiter: '?'
会让你使用<? ... ?>
而不是<% ... %>
。localsName
String 'locals'
用于存储在模板中使用的数据对象的变量名。通常不需要修改。 rmWhitespace
Boolean false
如果为 true
,会移除所有可安全移除的空白字符,可以减小 HTML 输出的大小。outputFunctionName
String 'print'
当 client
为true
时,用于设置编译函数中输出函数的名称。async
Boolean false
如果为 true
,EJS 将支持在模板中使用async/await
进行异步渲染。
1、服务端代码 (app.js):
const express = require('express');
const app = express();
const port = 3000;
// 1. 设置 EJS 为模板引擎
app.set('view engine', 'ejs');
app.get('/', (req, res) => {
// 2. 准备要传递给模板的数据
const data = {
title: 'My EJS Page',
user: { name: 'Alice' },
items: ['Apple', 'Banana', 'Orange']
};
// 3. 渲染 'views/index.ejs' 模板,并传入数据
res.render('index', data);
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
2、主模板 (views/index.ejs):
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<%- include('partials/header') %>
<h1>Hello, <%= user.name %>!</h1>
<ul>
<% items.forEach(function(item) { %>
<li><%= item %></li>
<% }); %>
</ul>
</body>
</html>
mysql
sequelize
redis
jest
项目介绍
演示地址: